
#include	"SysConfig.h"
#include	"Port.h"
#include	"Boot_Util.h"
#include	"Boot_FlashDrv.h"

#define COMPLETE            0x00                     /* FLASH write/erase complete */
#define DATA_PROGRAM_ERR    0x01                     /* FLASH data write error */
#define ERASE_ERR           0x02                     /* FLASH erase error */

#define ERS_CMD1            0x0020                   /* Block erase command 1 */
#define ERS_CMD2            0x00D0                   /* Block erase command 2 */
#ifdef  M16C_30PG
#define PRG_CMD             0x0040                   /* Program command */
#else
#define PRG_CMD             0x0041                   /* Program command */
#endif
#define STR_CLR             0x0050                   /* Status register clear command */

#pragma SECTION program UserBoot_Sector

/**********************************************************************************/
/*      CPU slow
/**********************************************************************************/
void cpu_slow()
{
    prcr  = 0x03;                /* CM0,CM1,CM2,FRA0,PLC0,PCLKR register protect off */
                                 /* PM0,PM1,PM2,TB2SC,INVC0,INVC1 register protect off */
    cm1   = 0x60;                /* Main clock division select: 2 division mode */
    cm0   = 0x08;                /* Main clock division select: CM16 and CM17 enabled */
    pm17  = 1;                   /* 1 wait */
    prcr  = 0x00;                /* Protect on */

}

/**********************************************************************************/
/*      CPU fast
/**********************************************************************************/
void cpu_fast()
{
    prcr  = 0x03;                /* CM0,CM1,CM2,FRA0,PLC0,PCLKR register protect off */
                                 /* PM0,PM1,PM2,TB2SC,INVC0,INVC1 register protect off */
    cm1   = 0x20;                /* Main clock division select: No division mode */
    cm0   = 0x08;                /* Main clock division select: CM16 and CM17 enabled */
    pm17  = 0;                   /* No wait */
    prcr  = 0x00;                /* Protect on */

}


/**********************************************************************************/
/*      command_write
/**********************************************************************************/
void BOOT_CommandWrite(unsigned short far *addr ,unsigned short *data){

//	asm("pushc flg");
//	asm("fclr i");                                   /* Interrupt disable */

	*addr = PRG_CMD;                                 /* Program command write */
	*addr = *data;                                   /* Lowwer data write */
#ifndef  M16C_30PG
	*addr = *(data + 1);                             /* Upper dara write */
#endif

//	asm("popc flg");

}

/**********************************************************************************/
/*      data_write
/**********************************************************************************/
unsigned char BOOT_FlashWrite(unsigned short far *write_addr, unsigned short *write_data, unsigned short usCnt)
{
	unsigned char program_result = COMPLETE;         /* Program result */
	unsigned int i;                                  /* Loop counter */

//	asm("pushc flg");

//	asm("fclr i");                                   /* Interrupt disable */

	cpu_slow();
#ifdef  M16C_64G
	/* Flash control register set */
	fmr0 = 0x01;
	asm(" ");        /* Description for preventing the abbreviation by optimization */
	fmr0 = 0x03;                                     /* CPU rewrite enable */

	fmr1 = 0x82;                                     /* FMR6 write enable */
	fmr6 = 0x03;                                     /* EW1 mode */
	fmr1 = 0x80;                                     /* FMR6 write disable */

	/* Write record data */
	for( i = 0; i < (usCnt/2); i+=2 ){
	//    BOOT_CommandWrite( &write_addr[i] ,&write_data[i] );   /* Program command write */
		write_addr[i] = PRG_CMD;
		write_addr[i] = *write_data;
		write_addr[i] = *(write_data + 1);
	    while( fmr00 == 0 );                         /* Ready check (0:busy / 1:ready) */

		++write_data;
		++write_data;
		
	    /* Program status check */
	    if( fmr06 == 1 ){
	        /* Program error */
	        *write_addr = STR_CLR;                   /* Clear status register */
	        program_result = DATA_PROGRAM_ERR;
	        break;
	    }
	}

	/* Flash control register reset */
	fmr0 = 0x01;                                     /* CPU rewrite disable */
#endif

#ifdef M16C_30PG

	prc1 = 1;
	pm17 = 1;	// with wait
	prc1 = 0;

	fmr01 = 0;
	fmr01 = 1;	// enable cpu rewrite mode

	fmr02 = 0;
	fmr02 = 1;

	fmr11 = 0;
	fmr11 = 1;	// EW1 mode

	//block 1 : rewrite enable
	fmr15 = 1;
	fmr15 = 0;

	//block 2 : rewrite enable
	fmr16 = 1;
	fmr16 = 0;

	//block 3 : rewrite enable
	fmr17 = 1;
	fmr17 = 0;

	/* Write record data */
	for( i = 0; i < (usCnt/2); ++i )
	{
		BOOT_CommandWrite( &write_addr[i] ,&write_data[i] );   /* Program command write */
		while( fmr00 == 0 );                         /* Ready check (0:busy / 1:ready) */

		if( fmr06 == 1 )
		{
			/* Program error */
			*write_addr = STR_CLR;                   /* Clear status register */
			program_result = DATA_PROGRAM_ERR;
			break;
		}
	}

	fmr01 = 0;  // disable cpu rewrite mode
	fmr02 = 0;  // block 0~3 Rewrite disabled

	//block 0 : rewrite disable 
	fmr14 = 0;
	fmr14 = 1;

	//block 1 : rewrite disable
	fmr15 = 0;
	fmr15 = 1;

	//block 2 : rewrite disable
	fmr16 = 0;
	fmr16 = 1;

	//block 3 : rewrite disable
	fmr17 = 0;
	fmr17 = 1;
	      /* CPU rewrite disable */
#endif

	cpu_fast();

	//	asm("popc flg");

	return program_result;
}


/**********************************************************************************/
/*      block_erase
/**********************************************************************************/
unsigned char BOOT_BlockErase(unsigned far *ers_addr){

    unsigned char erase_result;                      /* Erase result */
//	asm("pushc flg");
	//    asm("fclr i");                                   /* Interrupt disable */

	cpu_slow();
#ifdef  M16C_64G
	/* Flash control register set */
	fmr0 = 0x01;
	asm(" ");       /* Description for preventing the abbreviation by optimization */
	fmr0 = 0x03;                                     /* CPU rewrite enable */

	fmr1 = 0x82;                                     /* FMR6 write permission */
	fmr6 = 0x03;                                     /* EW1 mode */
	fmr1 = 0x80;                                     /* FMR6 write disable */

	*ers_addr = ERS_CMD1;                            /* Block erase command write */
	*ers_addr = ERS_CMD2;                            /* Block erase command write */

	while( fmr00 == 0 );                             /* Ready check (0:busy / 1:ready) */

	/* Erase status check */
	if( fmr07 == 1 ){
		*ers_addr = STR_CLR;                         /* Clear status register */
		erase_result = ERASE_ERR;
	}else{
		erase_result = COMPLETE;
	}

	/* Flash control register reset */
	fmr0 = 0x01;                                     /* CPU rewrite disable */
#endif

#ifdef  M16C_30PG
	
		prc1 = 1;
		pm17 = 1;	// with wait
		prc1 = 0;
		
		fmr01 = 0;
		fmr01 = 1;	// enable cpu rewrite mode
 
		fmr02 = 0;
		fmr02 = 1;
	
		fmr11 = 0;
		fmr11 = 1;	// EW1 mode
	 
		//block 1 : rewrite enable
		fmr15 = 1;
		fmr15 = 0;
		
		//block 2 : rewrite enable
		fmr16 = 1;
		fmr16 = 0;
		
		//block 3 : rewrite enable
		fmr17 = 1;
		fmr17 = 0;
 
	
	*ers_addr = STR_CLR;	/* Clear status register */
	*ers_addr = ERS_CMD1;	/* Block erase command write */
	*ers_addr = ERS_CMD2;	/* Block erase command write */
	while( fmr00 == 0 );	/* Ready check (0:busy / 1:ready) */

	/* Erase status check */
	if( fmr07 == 1 ){
		*ers_addr = STR_CLR;	/* Clear status register */
		erase_result = ERASE_ERR;
	}else{
		erase_result = COMPLETE;
	}
 
	fmr01 = 0; 	// disable cpu rewrite mode
	fmr02 = 0;	// block 0~3 Rewrite disabled
 
	//block 0 : rewrite disable 
	fmr14 = 0;
	fmr14 = 1;
	
	//block 1 : rewrite disable
	fmr15 = 0;
	fmr15 = 1;
	
	//block 2 : rewrite disable
	fmr16 = 0;
	fmr16 = 1;
	
	//block 3 : rewrite disable
	fmr17 = 0;
	fmr17 = 1;
#endif

	cpu_fast();

//	asm("popc flg");

	return  erase_result;
}

void BOOT_EraseAllBlock(void)
{
#ifdef  M16C_64G
	BOOT_BlockErase(ROM_BLOCK1_END);
	BOOT_BlockErase(ROM_BLOCK2_END);
	BOOT_BlockErase(ROM_BLOCK3_END);
	BOOT_BlockErase(ROM_BLOCK4_END);
	BOOT_BlockErase(ROM_BLOCK5_END);
	BOOT_BlockErase(ROM_BLOCK6_END);
#endif
#ifdef  M16C_30PG
	BOOT_BlockErase(ROM_BLOCK6_END);
	BOOT_BlockErase(ROM_BLOCK7_END);
	BOOT_BlockErase(ROM_BLOCK8_END);
#endif
}

/*//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////*/
// address fix
void BOOT_FlashMemory(unsigned char ucMode, unsigned long ucAddress, unsigned short *ucData)
{
	unsigned char i;
	
	if  (ucMode == 0)
	{	// Write
//		BOOT_memcpy(ucData,(unsigned  far *)ucAddress,64);
//		BOOT_BlockErase(0xCFFFE);	
//		BOOT_FlashWrite((unsigned short far *)0xC0000,ucData,64);
	}
	else
	{	// Read
	}
}

